;window.jQuery && (window.jQuery.fn.popin || (function($, window, undefined) {

// Esquive d'un bug de webkit avec les animation jQuery si le body est en position relative
	$(function() {
		if(navigator.userAgent.toLowerCase().indexOf('webkit') > -1) {
			$(document.body).css('position', 'static');
		}
	});

// Variables communes aux diverses composantes
	var animableProperties = ['top', 'left', 'width', 'height', 'marginLeft', 'marginTop', 'opacity'];

	window.masque = (function() {
		var currentMasque = false;
		$(window)
			.bind(
				 'keypress.masque'
				,function(e) {
					if(e.keyCode === 27) {
						if(currentMasque)
							currentMasque.hide();
					}
			})
			.bind(
				 'masqueHide'
				,function() {
					if(currentMasque)
						currentMasque.hide();
			})
			.bind(
				 'masqueShow'
				,function() {
					if(currentMasque)
						currentMasque.show();
			});

		return function(aArgs) {
			if(this.constructor !== arguments.callee) {
				return new arguments.callee(aArgs);
			}

			var $this = this
			,overlay
			,content
			,visible = false
			,showing = false
			,hiding = false

			,init = function() {
				$(window)
					.unload(destroy);

				if(!currentMasque)
					currentMasque = $this;

				if(typeof aArgs === 'object') {
					$.each(['preShow', 'postInsert', 'postShow', 'preHide', 'postHide'], function(key, value) {
						if(aArgs[value] !== undefined) {
							if(aArgs[value].constructor === Array && typeof aArgs[value][0] === 'function')
								$this.callbacks(value, aArgs[value][0], aArgs[value][1]);
							else if(aArgs[value].constructor === Function)
								$this.callbacks(value, aArgs[value]);
						}
					});
					for(var key in $this.options()) {
						if(aArgs[key] !== undefined) {
							$this.options(key, aArgs[key]);
						}
					}
					if(typeof aArgs['css'] === 'object') {
						$this.css(aArgs['css']);
					}
				}

				if($.browser.msie && $.browser.version < 7) {
					$(window)
						.resize(ie6RefreshAll)
						.scroll(ie6RefreshAll);
				}
			}

			,destroy = function() {
				overlay = false;
				content = false;
			}

			,ie6RefreshOverlay = function() {
				if(!$.browser.msie || $.browser.version > 7 || !visible)
					return;
				overlay
					.height($(document).height())
					.width($(document).width())
					.css({
						 top		: '-'+$(document.body).css('margin-top')
						,left		: '-'+$(document.body).css('margin-left')
					});
			}

			,ie6RefreshContent = function() {
				if(!$.browser.msie || $.browser.version > 7 || !visible)
					return;
				content
					.height(document.documentElement.clientHeight - parseInt($(document.body).css('margin-top')) - parseInt($(document.body).css('margin-bottom')))
					.width(document.documentElement.clientWidth - parseInt($(document.body).css('margin-left')) - parseInt($(document.body).css('margin-right')))
					.css({
						 top		: $(document).scrollTop()
						,left		: $(document).scrollLeft()
					});
			}

			,ie6RefreshAll = function() {
				overlay.trigger('refresh');
				content.trigger('refresh');
			}

			,contentClick = function(e) {
				if(		e.target === this
						|| $(e.target).hasClass($this.options('closeCls'))
						|| $(e.target).parents('.'+$this.options('closeCls')).length) {
					$this.hide();
				}
			}

			,doShow = function() {
				overlay = $('<div />')
					.css($.extend($this.css(), $this.options('cssPreShow')))
					.hide()
					.appendTo(document.body)
					.bind('close', $this.hide)
					.bind('click', $this.hide)
					.after(
						content = $('<div />')
							.css($this.cssContent())
							.bind('close', $this.hide)
							.bind('click', contentClick)
					)
					.animate(
						 $this.css(animableProperties)
						,$this.options('showSpeed')
						,function() {
							visible = true;
							showing = false;
							if($.browser.msie && $.browser.version < 7) {
								$this.callbacks('postShow', ie6RefreshAll, 1);
							}
							$this.callbacks('postShow');
						}
					);

				if($.browser.msie && $.browser.version < 7) {
					$this.callbacks('postInsert', function() {
						overlay
							.bind('refresh', ie6RefreshOverlay);
						content
							.bind('refresh', ie6RefreshContent);
					}, 1);
				}
				$this.callbacks('postInsert');
			}

			,doHide = function() {
				if($.browser.msie && $.browser.version < 7) {
					overlay
						.css($this.css(['height', 'width', 'top', 'left']));
				}
				overlay
					.animate(
						 $this.options('cssPostHide')
						,$this.options('hideSpeed')
						,function() {
							content
								.remove();
							$(this)
								.remove();
							hiding = false;
							visible = false;
							$this.callbacks('postHide');
						}
					);
			};

			this.show = function(fnCallback) {
				if(currentMasque && currentMasque !== $this) {
					currentMasque.hide(function() {
						currentMasque = $this;
						$this.show(fnCallback);
					});
					return;
				}
				if(visible) {
					if(typeof fnCallback === 'function')
						fnCallback.call($this);
					return;
				}
				if(typeof fnCallback === 'function')
					$this.callbacks('postShow', fnCallback, 1);
				if(showing)
					return;
				showing = true;
				$this.callbacks('preShow', doShow, 1);
				$this.callbacks('preShow');
			};

			this.hide = function(fnCallback) {
				if(showing) {
					$this.callbacks('postShow', function() {$this.hide(fnCallback)}, 1);
					return;
				}
				if(!visible) {
					if(typeof fnCallback === 'function')
						fnCallback.call($this);
					return;
				}
				if(typeof fnCallback === 'function')
					$this.callbacks('postHide', fnCallback, 1);
				if(hiding) {
					return;
				}
				hiding = true;
				$this.callbacks('preHide', doHide, 1);
				$this.callbacks('preHide');
			};

			this.visible = function(bSet, fnCallback) {
				if(typeof bSet === 'boolean') {
					if(bSet)
						$this.show(fnCallback);
					else
						$this.hide(fnCallback);
				}
				return visible || showing;
			};


			this.hiding = function() {
				return hiding;
			};

			this.overlay = function() {
				return overlay;
			};

			this.content = function() {
				return content;
			};

			this.css		= window.dynamicOptionsManager(this, window.masque.defaultCss);
			this.cssContent	= window.dynamicOptionsManager(this, window.masque.defaultCssContent);
			this.options	= window.dynamicOptionsManager(this, window.masque.defaultOptions);
			this.callbacks	= window.callbacksManager(this);

			init();
		};
	})();

	window.masque.defaultCss = {
		 position			: ($.browser.msie && $.browser.version < 7) ? 'absolute' : 'fixed'
		,'z-index'			: 9000
		,top				: ($.browser.msie && $.browser.version < 7) ? function() { return $(document).scrollTop() - parseInt($(document.body).css('margin-top'));} : 0
		,left				: ($.browser.msie && $.browser.version < 7) ? function() { return $(document).scrollLeft() - parseInt($(document.body).css('margin-left'));} : 0
		,marginLeft			: 0
		,marginTop			: 0
		,background			: 'black'
		,opacity			: '0.8'
		,width				: ($.browser.msie && $.browser.version < 7) ? function() { return document.documentElement.clientWidth;} : '100%'
		,height				: ($.browser.msie && $.browser.version < 7) ? function() { return document.documentElement.clientHeight;} : '100%'
	};

	window.masque.defaultCssContent = {
		 position			: ($.browser.msie && $.browser.version < 7) ? 'absolute' : 'fixed'
		,'z-index'			: function() { return this.css('z-index') + 1;}
		,top				: ($.browser.msie && $.browser.version < 7) ? function() { return '-'+$(document.body).css('margin-top');} : 0
		,left				: ($.browser.msie && $.browser.version < 7) ? function() { return '-'+$(document.body).css('margin-left');} : 0
		,width				: '100%'
		,height				: ($.browser.msie && $.browser.version < 7) ? function() { return document.documentElement.clientHeight;} : '100%'
	};

	window.masque.defaultOptions = {
		 showSpeed		: 'normal'
		,hideSpeed		: 'normal'
		,closeCls		: 'closePopin'
		,cssPreShow		: { opacity : 0 }
		,cssPostHide	: { opacity : 0 }
	};

	window.popin = function(mSelector, aArgs) {
		if(this.constructor !== arguments.callee) {
			return new arguments.callee(mSelector, aArgs);
		}

		var $this = this
		,ctntSelector = mSelector
		,skinsLoaded = []
		,ctnr = $('<div />')
		,ctnt = $('<div />')
		,visible = false
		,initOk = false
		,size = {}
		,masque = window.masque(aArgs !== undefined ? aArgs.masque : undefined)

		,init = function() {
			if(typeof aArgs == 'object') {
				$.each(['postInsert', 'preShow', 'postShow', 'preHide', 'postHide'], function(key, value) {
					if(aArgs[value] !== undefined) {
						if(aArgs[value].constructor === Array && aArgs[value].length === 2 && typeof aArgs[value][0] == 'function' && typeof aArgs[value][1] == 'number') {
							$this.callbacks(value, aArgs[value][0], aArgs[value][1]);
						}
						else if(aArgs[value].constructor === Function || aArgs[value].constructor === Array) {
							$this.callbacks(value, aArgs[value]);
						}
					}
				});
				for(var key in aArgs) {
					if(key !== 'skin' && $this.options.defined(key)) {
						$this.options(key, aArgs[key]);
					}
				}
				if(aArgs['skin'] !== undefined) {
					$this.options('skin', [aArgs['skin'], $this.options.raw('skin')]);
				}
				if(typeof aArgs['css'] == 'object')
					$this.css(aArgs['css']);
			}

			masque.callbacks('preHide', hide);
			masque.callbacks($this.options('waitBeforeShowingPopin') ? 'postShow' : 'postInsert', show);
			$this.container($this.options('skin'));
			initOk = true;
			if(ctntSelector)
				$this.content(ctntSelector);
			if($this.options('autoShow'))
				show();
		}

		,show = function(fnCallback) {
			if(visible) {
				if(typeof fnCallback == 'function')
					fnCallback.call($this);
				return;
			}
			if(typeof fnCallback == 'function')
				$this.callbacks('postShow', fnCallback, 1);
			if(!masque.visible()) {
				masque.show();
				return;
			}
			$this.callbacks('preShow', doShow, 1);
			$this.callbacks('preShow');
		}

		,doShow = function() {
			var cssFull = $this.css()
			,cssPreShow = $.extend({}, cssFull, $this.options('cssPreShow'))
			,cssPostShow = {};
			$.each(animableProperties, function(key, value) {
				if(cssFull[value] !== undefined && cssFull[value] !== cssPreShow[value])
					cssPostShow[value] = cssFull[value];
			});
			visible = true;
			ctnr
				.css(cssPreShow)
				.each(function() {
					if($this.options('hideChildren')) {
						ctnt
							.children()
								.hide()
					}
				})
				.appendTo(masque.content())
				.animate(
					 cssPostShow
					,$this.options('showSpeed')
					,function() {
						if($this.options('hideChildren')) {
							ctnt
								.children()
									.show()
						}
						if($.browser.msie) {
							$(this).children().each(function() {
								$(this).attr('style', ($(this).attr('style') || '').replace(/display\s*:\s*(inline)\s*;?/i, '') || false);
							});
							if($(this).css('opacity') == 1)
								$(this).attr('style', ($(this).attr('style') || '').replace(/filter\s*:\s*alpha[^;]*(;|$)/i, '') || false);
						}
						$this.callbacks('postShow', $this.refreshSize, 1);
						$this.callbacks('postShow');
					}
				);
		}

		,hide = function(fnCallback) {
			if(!visible) {
				if(typeof fnCallback == 'function')
					fnCallback.call($this);
				return;
			}
			if(typeof fnCallback == 'function')
				$this.callbacks('postHide', fnCallback, 1);
			if(!masque.hiding()) {
				masque.hide();
				return;
			}
			$this.callbacks('preHide', doHide, 1);
			$this.callbacks('preHide');
			if(typeof arguments.callee.continuer === 'function' && $this.options('waitBeforeHidingMasque')) {
				$this.callbacks('postHide', arguments.callee.continuer, 1);
				return false;
			}
		}

		,doHide = function() {
			visible = false;
			ctnr
				.each(function() {
					if($this.options('hideChildren')) {
						ctnt
							.children()
								.hide()
					}
				})
				.animate(
					 $this.options('cssPostHide')
					,$this.options('hideSpeed')
					,function() {
						$(this)
							.remove()
							.bind('popinShow', show);
						if($this.options('hideChildren')) {
							ctnt
								.children()
									.show()
						}
						$this.callbacks('postHide');
					}
				);
		}

		,loadSkin = function(skin) {
			if(!skin || skinsLoaded[skin] !== undefined) {
				return;
			}
			else {
				skinsLoaded[skin] = true;
				if(typeof skin === 'string' && $this.skins.defined(skin)) {
					skin = $this.skins(skin) || ctnr;
				}
				if(skin.constructor === Array) {
					for(var i in skin) {
						loadSkin(skin[i]);
					}
					return;
				}
				if(!(typeof skin === 'string' || skin.nodeType) || $(skin).length === 0)
					return;
				ctnr = $(skin);
			}
		};

		this.css		= window.dynamicOptionsManager(this, window.popin.defaultCss);
		this.skins		= window.dynamicOptionsManager(this, window.popin.skins);
		this.options	= window.dynamicOptionsManager(this, window.popin.defaultOptions);
		this.callbacks	= window.callbacksManager(this, window.popin.defaultCallbacks);

		this.show = masque.show;
		this.hide = masque.hide;

		this.container = function(skin) {
			if(arguments.length === 0) {
				return ctnr;
			}

			contentElements = $this.content();

			loadSkin(skin);

			ctnr
				.addClass($this.options('clsContainer'))
				.css($this.css(['position', 'overflow']))
				.unbind('refresh')
				.bind('refresh', $this.refreshSize)
				.each(function() {
					ctnt = $(this)
						.find('.'+$this.options('clsContent')+':first')
						.empty()
						.append(contentElements);
					if(ctnt.length === 0) {
						ctnt = $('<div class="'+$this.options('clsContent')+'" />')
							.append(contentElements)
							.appendTo($(this));
					}
				});
		};

		this.content = function(mSelector, postInsert) {
			if(arguments.length === 0) {
				return initOk ? ctnt.contents() : ctntSelector;
			}
			if(!initOk) {
				ctntSelector = mSelector;
			}
			else {
				if(typeof postInsert === 'function')
					$this.callbacks('postInsert', postInsert, 1);
				ctnt
					.empty()
					.append(mSelector);
				$this.initSize();
				$this.callbacks('postInsert');
			}
		};

		this.initSize = function() {
			if(!visible) {
				ctnr
					.css({
						 top: '-200%'
						,left: '-200%'
						,opacity: 0
					})
					.appendTo('body');
				$this.refreshSize(false);
				ctnr
					.remove();
			}
			else {
				$this.refreshSize();
			}
		};

		this.refreshSize = function(autoRefreshPosition) {
			var oldSize = size;
			ctnr
				.css({
					 height: 'auto'
					,width: 'auto'
				});
			size = {
				  width: ctnr.width()
				 ,height: ctnr.height()
			};
			ctnr
				.css($this.css(['height', 'width']));
			if(autoRefreshPosition !== false) {
				if(oldSize.width != size.width || oldSize.height != size.height)
					$this.refreshPosition();
			}
		};

		this.refreshPosition = function() {
			ctnr
				.animate(
						 $this.css(['top', 'left', 'marginLeft', 'marginTop'])
						,$this.options('refreshPositionSpeed')
				);
		};

		this.size = function(newSize) {
			if(arguments.length === 0) {
				return size;
			}
			size = {
				  width: newSize.width
				 ,height: newSize.height
			};
		};

		this.masque = function() {
			return masque;
		};

		init();
	};

	window.popin.skins = {
		 closeBtn		: function() {
							var cssPreShow = this.options('cssPreShow')
							,cssPostHide = this.options('cssPostHide')
							,closeCls = this.masque().options('closeCls');
							if(cssPreShow && (cssPreShow.height !== undefined || cssPreShow.width !== undefined)) {
								this.callbacks({
									 postShow	: function() {
													this.container()
														.children('.'+closeCls)
															.show();
												}
									,preShow	: function() {
													this.container()
														.children('.'+closeCls)
															.hide();
												}
								});
							}
							if(cssPostHide && (cssPostHide.height !== undefined || cssPostHide.width !== undefined)) {
								this.callbacks({
									 preHide	: function() {
													this.container()
														.children('.'+closeCls)
															.hide();
												}
								});
							}
							return this.container()
								.append(
									$('<div class="'+closeCls+'" />')
										.css({
											 position	: 'absolute'
											,top		: '-15px'
											,right		: '-15px'
											,cursor		: 'pointer'
										})
										.append('<img src="closepopin.png" alt="Fermer" />')
								);
						}
		,ajaxLink		: function() {
							var contentUrl = this.content();
							this.content('');
							this.callbacks('preShow', [function() {
								var continuer = arguments.callee.continuer
								,$this = this;
								$.get(
									 contentUrl
									,function(data) {
										$this.content(data);
										continuer();
									}
								);
								return false;
							}, 1]);
						}
	};

	window.popin.defaultCss = {
		 position		: 'absolute'
		,background		: 'white'
		,overflow		: 'visible'
		,left			: function() {return (this.size().width > this.masque().overlay().width()) ? '0' : '50%';}
		,top			: function() {return (this.size().height > this.masque().overlay().height()) ? '0' : '50%';}
		,height			: function() {return this.size().height;}
		,width			: function() {return this.size().width;}
		,marginTop		: function() {return (this.size().height > this.masque().overlay().height()) ? '0' : '-' + this.size().height / 2 + 'px';}
		,marginLeft		: function() {return (this.size().width > this.masque().overlay().width()) ? '0' : '-' + this.size().width / 2 + 'px';}
		,opacity		: 1
	};

	window.popin.defaultOptions = {
		 autoShow				: true
		,waitBeforeHidingMasque	: true
		,waitBeforeShowingPopin	: true
		,hideChildren			: true
		,showSpeed				: 'slow'
		,hideSpeed				: 'slow'
		,refreshPositionSpeed	: 'slow'
		,clsContainer			: 'popinContainer'
		,clsContent				: 'popinContent'
		,skin					: false
		,cssPreShow				: {
									 opacity	: 0
								}
		,cssPostHide			: {
									 opacity	: 0
								}
	};

	window.popin.defaultCallbacks = {};

	$.fn.popinTrigger = function(oContent, aArgs, sEvent) {
		if(arguments.length == 2 && typeof aArgs == 'string') {
			sEvent = aArgs;
			aArgs = undefined;
		}

		if(sEvent == undefined)
			sEvent = 'click';

		return this
			.each(function() {
				$(this)
					.bind(sEvent, (function(trigger) {
						var myPopin
						,ret = (sEvent == 'click' && trigger.is('a')) ? false : undefined
						,first = function() {
							myPopin = window.popin((typeof oContent == 'function') ? oContent.call(trigger) : oContent, aArgs);
							action = than;
							return ret;
						}
						,than = function() {
							myPopin.show();
							return ret;
						}
						,action = first;
						return function() {return action();};
					})($(this)));
			});
	};

	$.fn.popinAjaxTrigger = function(contentUrl, aArgs, sEvent) {
		if(!/^(string|function)$/.test(typeof contentUrl)) {
			sEvent = aArgs;
			aArgs = typeof contentUrl === 'object' ? contentUrl : {};
			contentUrl = function() {
				return $(this).attr('href');
			};
		}
		else if(typeof aArgs === 'string') {
			var e = sEvent;
			sEvent = aArgs;
			aArgs = typeof e === 'object' ? e : {};
		}
		return this
			.each(function() {
				(aArgs || (aArgs = {})).skin = ['ajaxLink', (aArgs || {}).skin];
				$(this)
					.popinTrigger(contentUrl, aArgs, sEvent);
			});
	};
})(window.jQuery, this));